package com.swak.vertx.security.realm;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Function;

import org.springframework.beans.factory.annotation.Autowired;

import com.swak.Constants;
import com.swak.cache.Entity;
import com.swak.security.AuthorizationInfo;
import com.swak.security.Principal;
import com.swak.security.Subject;
import com.swak.vertx.cache.SecurityCacheService;

/**
 * 提供缓存的支持
 *
 * @author: lifeng
 * @date: 2020/3/29 20:44
 */
public abstract class CachedRealm implements Realm {

	/**
	 * 缓存的名称
	 */
	protected int timeOut = Constants.Cache_Security_Idle;
	private final Function<Entity<AuthorizationInfo>, AuthorizationInfo> Handler;

	@Autowired(required = false)
	private SecurityCacheService cache;

	public CachedRealm() {
		this.Handler = (e) -> e.getValue();
	}

	public int getTimeOut() {
		return timeOut;
	}

	public void setTimeOut(int timeOut) {
		this.timeOut = timeOut;
	}

	/**
	 * 优先获取缓存中的数据
	 */
	@Override
	public CompletionStage<AuthorizationInfo> doGetAuthorizationInfo(Subject subject) {
		String keyName = subject.getPrincipal().toString();
		return cache.getObject(keyName).thenCompose(value -> {
			if (value == null) {
				return this.getAuthorizationInfo(subject.getPrincipal())
						.thenCompose(authorization -> cache.putObject(keyName, authorization, timeOut))
						.thenApply(this.Handler);
			}
			return CompletableFuture.completedFuture(value);
		});
	}

	/**
	 * 获取权限信息
	 *
	 * @param principal 身份信息
	 * @return 异步权限信息
	 */
	protected abstract CompletionStage<AuthorizationInfo> getAuthorizationInfo(Principal principal);

	/**
	 * 删除单个用户的缓存
	 *
	 * @param principal 身份信息
	 */
	public void clearCachedAuthorizationInfo(Principal principal) {
		cache.delete(principal.toString());
	}
}